home *** CD-ROM | disk | FTP | other *** search
- /*
- **
- ** $Id: bchanneljobs.c,v 1.1 1995/07/13 02:53:15 chris Exp $
- ** $Revision: 1.1 $
- **
- ** $Filename: developer/bchanneljobs.c $
- ** $Author: chris $
- ** $Date: 1995/07/13 02:53:15 $
- ** $Portability: ANSI $
- **
- ** B-Kanal Lese/Schreibjobs
- **
- ** THIS IS UNPUBLISHED PROPRIETARY SOURCE CODE OF RELOG AG.
- **
- ** COPYRIGHT (C) 1992-1995 BY RELOG AG, ZUERICH. ALL RIGHTS RESERVED.
- ** NO PART OF THIS SOFTWARE MAY BE COPIED, REPRODUCED, OR TRANSMITTED
- ** IN ANY FORM OR BY ANY MEANS, WITHOUT THE PRIOR WRITTEN PERMISSION
- ** OF RELOG AG.
- **
- */
-
- #include "os.h"
- #include "capi-usr.h"
-
- #define _BCHANNELJOBS
- #include "bchanneljobs.h"
- #include "alaw.h"
- #include "am.h"
- #include "process.h"
-
-
- static U8 __far tempbuf8[B_BLOCKSIZE];
- static S16 __far tempbuf16[B_BLOCKSIZE];
- static S16 __far mixbuf16[B_BLOCKSIZE];
-
-
- /*
- ** Sound mixen, volume = 0..B_VOLUME_MAX
- */
- static U16 MixIn( S16 *from, S16 *to, U16 len, U16 volume, U16 endvolume )
- {
- while (len)
- {
- #if 1
- S32 s = (((S32)*from++ * volume) >> B_VOLUME_SHIFT) + *to;
- #else
- S32 s = (S32)*from++ + *to;
- #endif
-
- if (s < -32768)
- s = -32768;
-
- if (s > 32767)
- s = 32767;
-
- *to++ = (S16)s;
-
-
- /*
- ** Der megacoole Fader
- */
- if (volume > endvolume)
- volume--;
- else if (volume < endvolume)
- volume++;
-
-
- len--;
- }
-
- return volume;
- }
-
-
- /*
- ** Einsprung des File I/O-Prozesses eines B-Kanals
- */
- static BOOL __saveds IOProcFunc( struct BChannel *bc )
- {
- struct BChannel_Job *job;
- static S16 inuse;
-
- /*
- ** Sicherstellen, dass wir nicht 2x gleichzeitig laufen
- */
- if (++inuse > 1)
- {
- inuse--;
- return TRUE;
- }
-
-
- /*
- ** Alle Jobs abarbeiten
- */
- redo:
- DOLIST( &bc->JobList, job )
- {
- struct Buffer *buf = job->PlayBuffer;
-
- if (buf->EndOfFile)
- continue;
-
- if (job->Flags & JOBF_WRITE) /* File --> B-Kanal */
- {
- if (buf->ActLength == 0) /* Puffer leer ? */
- {
- U16 rest;
-
- /* printf( "Reading %ld bytes\n", (U32)buf->TotalLength ); */
- buf->Position = buf->Data;
- buf->ActLength = (U16)fread( buf->Data, 1, buf->TotalLength, job->File );
-
- rest = buf->TotalLength - buf->ActLength;
- if (rest && (job->Flags & JOBF_LOOP))
- {
- /* printf( "Rewinding file.\n" ); */
- rewind( job->File );
- buf->ActLength += fread( buf->Data + buf->ActLength, 1, rest, job->File );
- }
-
- if (buf->ActLength == 0)
- buf->EndOfFile = TRUE;
-
- goto redo;
- }
- }
- else if (job->Flags & JOBF_READ) /* B-Kanal --> File */
- {
- if (buf->ActLength == buf->TotalLength) /* Puffer voll ? */
- {
- buf->Position = buf->Data;
- /* printf( "Writing file\n" ); */
- fwrite( buf->Data, 1, buf->ActLength, job->File );
- buf->ActLength = 0;
-
- goto redo;
- }
- }
- }
-
- inuse--;
- return TRUE;
- }
-
-
- /****** BChannel_New ********************************************************
- *
- * NAME
- * BChannel_New -- Create a new B-channel entity
- *
- * SYNOPSIS
- * channel = BChannel_New( ncci )
- *
- * struct BChannel *BChannel_New( U32 );
- *
- * FUNCTION
- *
- * INPUTS
- *
- * RESULTS
- *
- * SEE ALSO
- *
- ****************************************************************************/
-
- struct BChannel *
- BChannel_New( U32 NCCI )
- {
- struct BChannel *bc;
-
- if ((bc = OS_Malloc( sizeof( *bc ) )) != NULL)
- {
- bc->NCCI = NCCI;
-
- NEWLIST( &bc->JobList );
-
- if (bc->IOProcess = Process_Create( IOProcFunc, bc, "AM-IO", 4 ))
- {
- USES_DISABLE
-
- bc->Buf1.Position = bc->Buf1.Data;
- bc->Buf2.Position = bc->Buf2.Data;
- bc->Buf1.TotalLength = sizeof( bc->BD1 );
- bc->Buf2.TotalLength = sizeof( bc->BD2 );
-
- bc->WriteBuffer = &bc->Buf1;
- bc->PlayBuffer = &bc->Buf2;
-
- DISABLE;
- ADDTAIL( &bchannellist, &bc->Node );
- ENABLE;
- }
- else
- {
- printf( "Can't create B-channel I/O process\n" );
- OS_Free( bc );
- bc = NULL;
- }
- }
-
- return bc;
- }
-
-
- /****** BChannel_Free *******************************************************
- *
- * NAME
- * BChannel_Free -- Free a B-channel entity
- *
- * SYNOPSIS
- * BChannel_Free( bc )
- *
- * VOID BChannel_Free( struct BChannel * );
- *
- * FUNCTION
- *
- * INPUTS
- *
- * RESULTS
- *
- * SEE ALSO
- *
- ****************************************************************************/
-
- VOID
- BChannel_Free( struct BChannel *bc )
- {
- if (bc != NULL)
- {
- USES_DISABLE
-
- DISABLE;
-
- while (!ISLISTEMPTY( &bc->JobList))
- {
- BChannel_FreeJob( (struct BChannel_Job *)bc->JobList.Head );
- }
-
- REMOVE( &bc->Node );
-
- Process_Delete( bc->IOProcess );
- /* bc->IOProcess = NULL; */
-
- ENABLE;
-
- OS_Free( bc );
- }
- }
-
-
- /****** BChannel_Find *******************************************************
- *
- * NAME
- * BChannel_Find -- Find a B-channel entity by its NCCI
- *
- * SYNOPSIS
- * bc = BChannel_Find( ncci )
- *
- * struct BChannel *BChannel_Find( U32 );
- *
- * FUNCTION
- *
- * INPUTS
- *
- * RESULTS
- *
- * SEE ALSO
- *
- ****************************************************************************/
-
- struct BChannel *
- BChannel_Find( U32 ncci )
- {
- struct BChannel *bc, *result = NULL;
- USES_DISABLE
-
- DISABLE;
-
- DOLIST( &bchannellist, bc )
- {
- if (bc->NCCI == ncci)
- {
- result = bc;
- break;
- }
- }
-
- ENABLE;
-
- return result;
- }
-
-
- /****** BChannel_AddJob *****************************************************
- *
- * NAME
- * BChannel_AddJob -- Add a read/write job to a B-channel
- *
- * SYNOPSIS
- * bc = BChannel_AddJob( bc, filename, flags, U16 volume, sigproc )
- *
- * struct BChannel_Job *BChannel_AddJob( struct BChannel *,
- * U8 *, U16, U16, U32 );
- *
- * FUNCTION
- *
- * INPUTS
- * bc - B-channel to add job to
- * filename - File to read / write data
- * flags - JOBF_...
- * volume - 0..B_VOLUME_MAX
- * sigproc - Process to signal when the job is terminated
- *
- * RESULTS
- *
- * SEE ALSO
- *
- ****************************************************************************/
-
- struct BChannel_Job *
- BChannel_AddJob( struct BChannel *bc, U8 *filename, U16 flags, U16 volume, U32 sigproc )
- {
- if ((bc != NULL) && (filename != NULL))
- {
- struct BChannel_Job *job;
-
- /* printf( "Adding %s job '%s'\n", (flags & JOBF_READ) ? "READ" : "WRITE", filename ); */
-
- if ((job = OS_Malloc( sizeof( *job ) )) != NULL)
- {
- job->Flags = flags;
- job->ActVolume = volume;
- job->EndVolume = volume;
- job->SigProc = sigproc;
-
- job->Buf1.Position = job->Buf1.Data;
- job->Buf2.Position = job->Buf2.Data;
- job->Buf1.TotalLength = sizeof( job->BD1 );
- job->Buf2.TotalLength = sizeof( job->BD2 );
-
- job->BChannel = bc;
-
- job->WriteBuffer = &job->Buf1;
- job->PlayBuffer = &job->Buf2;
-
- if (job->File = fopen( filename, (flags & JOBF_WRITE) ? "r" : "w" ))
- {
- BOOL firsttime = ISLISTEMPTY( &bc->JobList );
- USES_DISABLE;
-
- setbuf( job->File, NULL ); /* Unbuffered i/o */
-
- DISABLE;
- ADDTAIL( &bc->JobList, &job->Node );
- ENABLE;
-
- IOProcFunc( bc ); /* Daten des neuen Files lesen */
-
- if (firsttime)
- {
- BChannel_DataB3Conf( bc->NCCI ); /* 2x für Doublebuffering */
- BChannel_DataB3Conf( bc->NCCI );
- }
-
- return job;
- }
- else
- {
- printf( "Can't open file '%s'\n", filename );
- }
-
- OS_Free( job );
- }
- }
-
- return NULL;
- }
-
-
- /****** BChannel_FreeJob ****************************************************
- *
- * NAME
- * BChannel_FreeJob -- Free a read/write job
- *
- * SYNOPSIS
- * BChannel_FreeJob( bc )
- *
- * VOID BChannel_FreeJob( struct BChannel * );
- *
- * FUNCTION
- * Removes the job if it's in the job list, and frees its resources.
- *
- * INPUTS
- *
- * RESULTS
- *
- * SEE ALSO
- *
- ****************************************************************************/
-
- VOID
- BChannel_FreeJob( struct BChannel_Job *job )
- {
- if (job != NULL)
- {
- USES_DISABLE
-
- DISABLE;
- if (job->Node.Succ != NULL)
- {
- REMOVE( &job->Node );
- job->Node.Succ = NULL;
- }
- ENABLE;
-
- if (job->File != NULL)
- {
- fclose( job->File );
- /* job->File = NULL; */
- }
-
- if (job->SigProc)
- {
- Process_WakeUp( job->SigProc );
- }
-
- OS_Free( job );
- }
- }
-
-
- /****** BChannel_DataB3Ind **************************************************
- *
- * NAME
- * BChannel_DataB3Ind -- Handle incoming data
- *
- * SYNOPSIS
- * BChannel_DataB3Ind( ncci, data, length )
- *
- * VOID BChannel_DataB3Ind( U32, U8 *, U16 );
- *
- * FUNCTION
- *
- * INPUTS
- *
- * RESULTS
- *
- * SEE ALSO
- *
- ****************************************************************************/
-
- VOID
- BChannel_DataB3Ind( U32 ncci, U8 *data, U16 length )
- {
- struct BChannel *bc;
-
- if (bc = BChannel_Find( ncci ))
- {
- struct BChannel_Job *job;
- BOOL work = FALSE;
-
- DOLIST( &bc->JobList, job )
- {
- if (job->Flags & JOBF_READ)
- {
- struct Buffer *buf = job->WriteBuffer;
- U16 wlen = buf->TotalLength - buf->ActLength;
-
- if (wlen > length)
- wlen = length;
-
- OS_memcpy( buf->Position, data, wlen );
- buf->Position += wlen;
- data += wlen;
- buf->ActLength += wlen;
-
- length -= wlen;
-
- if (buf->ActLength == buf->TotalLength) /* Puffer voll ? */
- {
- job->WriteBuffer = job->PlayBuffer; /* Swap */
- job->PlayBuffer = buf;
- buf = job->WriteBuffer;
-
- buf->Position = buf->Data; /* Neuen Buffer leeren */
- buf->ActLength = 0;
-
- if (length)
- {
- OS_memcpy( buf->Position, data, length );
- buf->Position += length;
- buf->ActLength += length;
- }
-
- work = TRUE;
- }
- }
- }
-
- if (work)
- Process_WakeUp( bc->IOProcess );
- }
- }
-
-
- /****** BChannel_DataB3Conf *************************************************
- *
- * NAME
- * BChannel_DataB3Conf -- Handle acknowledgement of outgoing data
- *
- * SYNOPSIS
- * BChannel_DataB3Conf( ncci )
- *
- * VOID BChannel_DataB3Conf( U32 );
- *
- * FUNCTION
- *
- * INPUTS
- *
- * RESULTS
- *
- * SEE ALSO
- *
- ****************************************************************************/
-
- VOID
- BChannel_DataB3Conf( U32 ncci )
- {
- struct BChannel *bc;
-
- if (bc = BChannel_Find( ncci ))
- {
- struct BChannel_Job *job;
- BOOL work = FALSE;
-
- struct
- {
- CAPI_MESSAGE Msg;
- U8 Para[14];
- } data_b3_req;
-
- U8 *para = data_b3_req.Para;
-
-
- OS_memset( mixbuf16, 0, sizeof( mixbuf16 ) );
-
-
- /*
- ** Daten aller Jobs zusammenmischen
- */
-
- DOLIST( &bc->JobList, job )
- {
- if (job->State == JOBSTATE_TERMINATED)
- continue;
-
- if (job->Flags & JOBF_WRITE)
- {
- struct Buffer *buf = job->WriteBuffer;
- U16 wlen = buf->ActLength;
-
- if (wlen > B_BLOCKSIZE)
- wlen = B_BLOCKSIZE;
-
- ALAW_ALawTo16Bit( buf->Position, tempbuf16, (U32)wlen );
- buf->Position += wlen;
- buf->ActLength -= wlen;
-
- job->ActVolume = MixIn( tempbuf16, mixbuf16, wlen, job->ActVolume, job->EndVolume );
-
- if (buf->ActLength == 0) /* Puffer leer ? */
- {
- job->WriteBuffer = job->PlayBuffer; /* Swap */
- job->PlayBuffer = buf;
- buf = job->WriteBuffer;
-
- if (buf->EndOfFile) /* Keine Daten mehr */
- {
- if (job->Flags & JOBF_AUTOFREE)
- {
- struct BChannel_Job *oldjob = job;
- job = (struct BChannel_Job *)oldjob->Node.Pred;
- BChannel_FreeJob( oldjob );
- }
- else
- {
- job->State = JOBSTATE_TERMINATED;
- }
- }
-
- work = TRUE;
- }
- }
- }
-
- ALAW_16BitToALaw( mixbuf16, bc->WriteBuffer->Data, (U32)bc->WriteBuffer->TotalLength );
-
-
- /*
- ** DATA_B3_REQ absenden
- */
- data_b3_req.Msg.Command = CAPICMD_DATA_B3;
- data_b3_req.Msg.Subcommand = CAPISUBCMD_REQ;
-
- ADD_PARA( para, U32, bc->NCCI );
- ADD_PARA( para, U8 *, bc->WriteBuffer->Data );
- ADD_PARA( para, U16, bc->WriteBuffer->TotalLength );
- ADD_PARA( para, U16, 0x1234 ); /* Data handle */
- ADD_PARA( para, U16, 0 ); /* Flags */
-
- SendCAPIMessage( &data_b3_req.Msg, para );
-
-
- /*
- ** Double buffering
- */
- {
- struct Buffer *tmp = bc->WriteBuffer;
- bc->WriteBuffer = bc->PlayBuffer;
- bc->PlayBuffer = tmp;
- }
-
- if (work)
- {
- /* printf( "DataB3Conf: waking up I/O process 0x%08lx\n", bc->IOProcess ); */
- Process_WakeUp( bc->IOProcess );
- }
- }
- }
-
-